use crate::vm::VirtualMachine;
use crate::error::Result;
use crate::vm::Value;
use std::io;

// 读取整数
pub fn native_read_int(vm: &mut VirtualMachine) {
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("Failed to read line");
    if let Ok(num) = input.trim().parse::<i32>() {
        let _ = vm.push_stack(Value::Integer(num));
    } else {
        let _ = vm.push_stack(Value::Integer(0));
    }
}

// 读取浮点数
pub fn native_read_float(vm: &mut VirtualMachine) {
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("Failed to read line");
    if let Ok(num) = input.trim().parse::<f64>() {
        let _ = vm.push_stack(Value::Float(num));
    } else {
        let _ = vm.push_stack(Value::Float(0.0));
    }
}

// 读取字符串
pub fn native_read_string(vm: &mut VirtualMachine) {
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let s = input.trim().to_string();
    let _ = vm.push_stack(Value::String(s));
}

// 打印整数
pub fn native_print_int(vm: &mut VirtualMachine) {
    if let Some(Value::Integer(i)) = vm.pop_stack() {
        println!("{}", i);
    }
}

// 打印浮点数
pub fn native_print_float(vm: &mut VirtualMachine) {
    if let Some(Value::Float(f)) = vm.pop_stack() {
        println!("{}", f);
    }
}

// 打印字符串
pub fn native_print_string(vm: &mut VirtualMachine) {
    if let Some(Value::String(s)) = vm.pop_stack() {
        println!("{}", s);
    }
}

// 获取环境变量
pub fn native_getenv(vm: &mut VirtualMachine) -> Result<()> {
    if let Some(Value::String(key)) = vm.pop_stack() {
        if let Ok(value) = std::env::var(&key) {
            let _ = vm.push_stack(Value::String(value));
        } else {
            let _ = vm.push_stack(Value::String("".to_string()));
        }
    } else {
        let _ = vm.push_stack(Value::String("".to_string()));
    }
    Ok(())
}

// 获取数组长度
pub fn native_array_length(vm: &mut VirtualMachine) -> Result<()> {
    if let Some(Value::Array(arr)) = vm.pop_stack() {
        let _ = vm.push_stack(Value::Integer(arr.len() as i32));
    } else {
        let _ = vm.push_stack(Value::Integer(0));
    }
    Ok(())
}